// Copyright DustedPixels.com 2008. All rights reserved.

package com.dustedpixels.jasmin.unit.z80.v1;

/**
 * @author micapolos@gmail.com (Michal Pociecha-Los)
 */
public final class MCycleController {

  public boolean OP_REQ;
  public int OP;
  public static final int OP_FETCH = 0x00;
  public static final int OP_READ = 0x01;
  public static final int OP_WRITE = 0x02;

  public int ADDR_ENABLE;

  public int DDD;
  public static final int DDD_NONE = 0x00; 
  public static final int DDD_REGS = 0x01; 
  public static final int DDD_ACC = 0x01; 
  public static final int DDD_TMP = 0x01;
  
  public boolean INC_PC;
  public boolean READY;
  
  private int opReg;
  private int cycleReg;
  
  public void updateSeq() {
    if (OP_REQ) {
      opReg = OP;
      cycleReg = 0;
    } else if (mCycleEnd) {
      opReg = 0;
      cycleReg = 0;
    } else if (!waitCheck | WAIT) {
      cycleReg++;
    }
      
    switch (opReg) {
      case OP_FETCH:
        switch (cycleReg) {
          case 0:
            ADDR_ENABLE = true;
            ctrlEnable = true;
            m1 = true;
            break;
          case 1:
            mreq = true;
            rd = true;
            break;
          case 2:
            waitCheck = true;
              mreq = true;
              rd = true;
            } else {
              ctrlEnable = true;
              rfsh = true;
              DATA_READY = true;
            }
            break;
          case 3:
            rfsh = true;
            mreq = true;
            mCycleEnd = true;
            break;
        }
        break;
      case OP_READ:
        switch (cycleReg) {
          case 0:
            ctrlEnable = true;
            m1 = false;
            rfsh = false;
            break;
          case 1:
            mreq = true;
            rd = true;
            break;
          case 2:
            if (WAIT) {
              waitCheck = true; 
            } else {
              mreq = true;
              rd = true;
              mCycleEnd = true;
              DATA_READY = true;
            }
            break;
        }
        break;
      case OP_WRITE:
        switch (cycleReg) {
          case 0:
            break;
          case 1:
            mreq = true;
            break;
          case 2:
            if (WAIT) {
              waitCheck = true; 
            } else {
              mreq = true;
              wr = true;
              mCycleEnd = true;
              DATA_READY = true;
            }
            break;
        }
        break;
    }
    
    MREQ = mreq | delay;
    RD = rd | delay;
  }
  
  public void clkHigh() {
    if (ctrlEnable) {
      M1 = m1;
      RFSH = rfsh;
    }
    
    if (OP_REQ) {
      opReg = OP;
      cycleReg = 0;
    } else if (mCycleEnd) {
      opReg = 0;
      cycleReg = 0;
    } else if (!waitCheck | WAIT) {
      cycleReg++;
    }
  }
}
